iT邦幫忙

2022 iThome 鐵人賽

DAY 15
3
tags: .NET6 C#, LineBot, Line Messaging API, C#, dotnet core

[Day 15] 讓 C# 也可以很 Social - .NET 6 C# 與 Line Services API 開 - Flex Message

前言

Hello 各位好,今天這篇要介紹 flex message 正是讓 Line Bot 成為現今如此熱門的行銷管道的一大要素,正如 "flex" 字面上的意思,開發者能夠相當程度上的客製化訊息的格式,並且也能做出 carousel 的輪播效果,所以開發者能夠將 Line Bot 依照要提供的服務不同,創造出獨特的風格與服務內容,不會像早期的 Line Bot,因為大家都使用相同的訊息格式導致 各個 Line Bot 之間的特色並不鮮明。

Flex Message 介紹 文件連結

屬性介紹

Flex 訊息格式設定的方式與 CSS Flexible Box 相似,但因為屬性實在太多,所以詳細的內容還是去Line官方文件內查看,這邊就先做個簡單的介紹後,透過實作來讓大家感受一下Flex的效果!

Flex Message 由 Container 與 Component 組成

  • Conatainer
    • Bubble : Bubbel 就是一個獨立的區塊,每個區塊內可以用 Component 去做出不同的訊息格式。
      • 而一個 Bubble 中共分成 4 個區塊
      • Header : Bubble 最上層,只能放 box componet
      • Hero : 可放 box, image, video compoenet
      • Body : 主要放內文的地方, 只能放 box component
      • Footer : Bubble 最下層,只能放 box component
      • 以上四個區域皆可自由選擇使用與否
    • Header
    • Carousel : Carousel 最多可以容納 12 個 Bubble,並且有跟上一篇介紹的 carousel template 一樣可橫向滑動的效果。
  • Component
    • Box : Bubble 中 layout 的基本單位,Box 中可以放入其他的 component,其作用是定義在他之下的 child component 的 layout 方式,並起到不同 layout 之間區隔的作用。
      詳細資料請參考 : 文件連結

    • Button : Button 元件一樣是被點擊後會執行設定好的Action。
      詳細資料請參考 : 文件連結

    • Image : 用來顯是圖片的元件,比較特別的是 image component 還可以設定放入動畫圖片

      詳細資料請參考 : 文件連結

    • Video : 播放影片的元件,但使用 video component 有以下限制

      • 元件所屬的 bubble 不可在 carousel 下。
      • Video 元件必須直接放在 bubble container Hero 區塊下。
      • bubble 的大小必須是 kilo、mega 或 giga 其中一個。
        詳細資料請參考 : 文件連結
    • Icon : 用於在文字前方標示圖案的元件,但其只能放在 layout 設為 baseline 的 box component 中使用。
      詳細資料請參考 : 文件連結

    • Text : 顯示文字的元件。
      詳細資料請參考 : 文件連結

    • Span : 也是用於顯示文字的元件,不過必須放在 text component 的 content 屬性中,每個 span 都可以設定自己的字體樣式,達到一個 text component 中有多種字體樣式的效果。
      詳細資料請參考 : 文件連結

    • Separator : 在 box component 中劃出一條線的元件,用於幫元件做分割,在水平 layout 的 box 中會畫出垂直線,在垂直 layout 的 box 中會畫出水平線。
      詳細資料請參考 : 文件連結

    • Filler : 在元件與元件之間做出空白的區隔。
      詳細資料請參考 : 文件連結

Class 宣告

在 MessageEnum.cs 中新增 Enum

public static class FlexContainerTypeEnum
{
    public const string Bubble = "bubble";
    public const string Carousel = "carousel";
}

在 Dtos/Messages 中宣告 FlexMessageDto.cs

using LineBotMessage.Enum;
namespace LineBotMessage.Dtos
{
    public class FlexMessageDto<T> : BaseMessageDto
    {
        public FlexMessageDto()
        {
            Type = MessageTypeEnum.Flex;
        }

        public string AltText { get; set; }
        public T Contents { get; set; }
    }

    // containers
    public class FlexBubbleContainerDto
    {
        public string Type { get; set; } = FlexContainerTypeEnum.Bubble;
        public string? Size { get; set; }
        public string? Direction { get; set; }

        public FlexComponentDto? Header { get; set; }
        public FlexComponentDto? Hero { get; set; }
        public FlexComponentDto? Body { get; set; }
        public FlexComponentDto? Footer { get; set; }
        public FlexComponentDto? Style { get; set; }
        public ActionDto? Action { get; set; }
    }

    public class FlexCarouselContainerDto
    {
        public string Type { get; set; } = FlexContainerTypeEnum.Carousel;
        public List<FlexBubbleContainerDto> Contents { get; set; }
    }

    // component
    public class FlexComponentDto
    {
        public string Type { get; set; }

        // box component
        public string? Layout { get; set; }
        public List<FlexComponentDto>? Contents { get; set; }
        public string? BackgroundColor { get; set; }
        public string? BorderColor { get; set; }
        public string? BorderWidth { get; set; }
        public string? CornerRadius { get; set; }
        public string? Width { get; set; }
        public string? MaxWidth { get; set; }
        public string? Height { get; set; }
        public string? MaxHeight { get; set; }
        public int? Flex { get; set; }
        public string? Spacing { get; set; }
        public string? Mergin { get; set; }
        public string? PaddingAll { get; set; }
        public string? PaddingTop { get; set; }
        public string? PaddingBottom { get; set; }
        public string? PaddingStart { get; set; }
        public string? PaddingEnd { get; set; }
        public string? Position { get; set; }
        public string? OffsetTop { get; set; }
        public string? OffsetBottom { get; set; }
        public string? OffsetStart { get; set; }
        public string? OffsetEnd { get; set; }
        public ActionDto? Action { get; set; }
        public string? JustifyContent { get; set; }
        public string? AlignItems { get; set; }
        public FlexBackgroundDto? Background { get; set; }

        // button coponent 
        public string? Style { get; set; }
        public string? Color { get; set; }
        public string? Gravity { get; set; }
        public string? AdjustMode { get; set; }

        //image component
        public string? Url { get; set; }
        public string? Align { get; set; }
        public string? Size { get; set; }
        public string? AspectRatio { get; set; }
        public string? AspectMode { get; set; }
        public bool? Animated { get; set; }

        //video component
        public string? PreviewUrl { get; set; }
        public string? AltContent { get; set; }

        //text component
        public string? Text { get; set; }
        public bool? Wrap { get; set; }
        public string? LineSpaceing { get; set; }
        public int? Maxlines { get; set; }
        public string? Wㄍight { get; set; }
        public string? Decoration { get; set; }

        //icon, span, separator, filler 屬性已宣告過
    }

    public class FlexBackgroundDto
    {
        public string? Type { get; set; }
        public string? Angle { get; set; }
        public string? StartColor { get; set; }
        public string? EndColor { get; set; }
        public string? CenterColor { get; set; }
        public string? CenterPosition { get; set; }
    }

    // bubble container styles
    public class FlexBubbleContainerStyle
    {
        public FlexBlockStyle? Header { get; set; }
        public FlexBlockStyle? Hero { get; set; }
        public FlexBlockStyle? Body { get; set; }
        public FlexBlockStyle? Footer { get; set; }
    }

    public class FlexBlockStyle
    {
        public string? BackgroundColor { get; set; }
        public bool? Separator { get; set; }
        public string? SeparatorColor { get; set; }
    }
}

測試

看到上面的宣告就知道,Flex 的製作非常複雜,若要使用程式內 class 傳送的方式實在太複雜,也沒辦法對訊息有畫面參考,所以 Line 有提供 Flex Simulator,能夠快速的製作出 flex,並產相對應的 Json 字串。

Flex Simulator 連結

  • 畫面中有三區塊,分別是

    • 訊息預覽視窗
    • 訊息元件列表
    • 元件屬性視窗
  • 按下右上角 Send 按鈕後也可以將目前製作的 flex 透過這支機器人傳送給你實際參考(第一次傳送時會要求將此機器人加為好友)。

  • 右上角的 Showcase 內有許多 Line 提供的 flex 範例,這次測試就選擇一個自己喜歡的範例吧。

  • 選好範例後按下 View as JSON 即可展開以下畫面,這些就是目前訊息的 Json 字串。

廣播測試

這次測試就使用 廣播的 API 吧!

  • 在 MessageTypeEnum 中新增兩個屬性
public const string FlexBubble = "flexBubble";
public const string FlexCarousel = "flexCarousel";
  • 在 LineBotService -> BroadcastMessageHandler function 中新增兩個 case
case MessageTypeEnum.FlexBubble:
    messageRequest = _jsonProvider.Deserialize<BroadcastMessageRequestDto<FlexMessageDto<FlexBubbleContainerDto>>>(strBody);
    break;

case MessageTypeEnum.FlexCarousel:
    messageRequest = _jsonProvider.Deserialize<BroadcastMessageRequestDto<FlexMessageDto<FlexCarouselContainerDto>>>(strBody);
    break;
  • Swagger 廣播 API 畫面

    • MessageType 根據你的範例類型帶入
    • Flex Simulator 產生的 JSON 不是直接放在 Messages 屬性下,而是 Flex Message 下的 Contents 屬性
  • 測試用 JSON Body

{
  "Messages": [
    {
      "Type": "flex",
      "AltText": "This is flex message",
      "Contents": //這裡放 flex simulator 產生的 JSON
    }
  ]
}
  • 廣播收到的訊息

結語

Flex 介紹結束後,就把 Line Bot 目前所有訊息格式介紹完了,目前的這些內容串連起來就能夠打造出一個內容豐富的 Line Bot,尤其是使用 flex 的訊息,才能夠讓 Line Bot 變得與眾不同。
下一篇開始會介紹 Line Bot 的 rich menu, rich menu 是顯示在 Line Bot 聊天室下方的選單,與 Image map 一樣是提供一張圖片後對圖片做區塊的分割,並設定點選後執行的動作,下一篇見!

腦筋急轉彎

  • 如果想要呈現的卡片超過十二個的時候,執行的結果會是如何?

範例程式碼

如果想要參考今天範例程式碼的部份,下面是 Git Repo 連結,方便大家參考。

Day15_Flex Message


上一篇
[Day 14].NET 6 C# 與 Line Services API 開發 - Template message 裏的 Carousel & Image Carousel
下一篇
[Day 16] .NET 6 C# 與 Line Services API 開發 - Rich Menu 製作(一) 起手式
系列文
讓 C# 也可以很 Social - 在 .NET 6 用 C# 串接 LINE Services API 的取經之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
柴柴
iT邦新手 5 級 ‧ 2022-10-02 23:46:00

你好,我想請教一下
當FlexMessage需要客製化的時候
例如: "text": "Brown Cafe" => "text": "Hello"
是不是還是要走FlexMessageDto.cs新建class方式去會比較好嗎?

因為以下這種方式會變成要用Replace的方式改Json內容
{
"Messages": [
{
"Type": "flex",
"AltText": "This is flex message",
"Contents": //這裡放 flex simulator 產生的 JSON
}
]
}
還是版大有還有什麼比較好維護FlexMessage的方式嗎
這問題困擾我很久 /images/emoticon/emoticon02.gif

APPX Jim iT邦新手 5 級 ‧ 2022-10-06 18:53:18 檢舉

在回答問題之前,先說明一下 目前手邊運作的機制 ~
Controller裏回傳資料的方式,是直接回傳自定義好的Model物件
而 JsonProvider 會依設定的格式自動先轉成對應的 json 再回傳給 line api


如果是依上述的說明,來回答上述的問題(FlexMessage需要客製化)
那就是 Model 物件裏的文字屬性(相對應的屬性) 修改

myDataModel.Contents = "新的內容";
然後 return myDataModel 即可~

(*如果是要用 replace json裏面的內容,感覺會很可怕 ~ 如果寫不小心,資料格式整個就會錯亂 !!!)

柴柴 iT邦新手 5 級 ‧ 2022-10-22 22:37:09 檢舉

真的很謝謝你!!
我大概知道怎麼做比較好了

我要留言

立即登入留言